﻿// <copyright file="IdentityErrorHandler.cs" company="SharpSTS">
// Copyright (c) 2007, 2008 All Right Reserved, http://sharpsts.com/
//
// This source is subject to the Microsoft Permissive License.
// Please see the License.txt file for more information.
// All other rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// </copyright>
// <author>Barry Dorrans</author>
// <email>barryd@idunno.org</email>
// <date>2008-06-11</date>
// <summary>Handles errors for the STS endpoints and marshalls them to the documented SOAP faults in the interop documentation.</summary>

namespace SharpSTS
{
    using System;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Dispatcher;

    /// <summary>
    /// Handles errors for the STS endpoints and marshalls them to the documented SOAP faults in the interop documentation.
    /// </summary>
    internal class IdentityErrorHandler : IErrorHandler
    {
        /// <summary>
        /// Enables the creation of a custom <see cref="T:System.ServiceModel.FaultException`1"/> that is returned from an exception in the course of a service method.
        /// </summary>
        /// <param name="error">The <see cref="T:System.Exception"/> object thrown in the course of the service operation.</param>
        /// <param name="version">The SOAP version of the message.</param>
        /// <param name="fault">The <see cref="T:System.ServiceModel.Channels.Message"/> object that is returned to the client, or service, in the duplex case.</param>
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            // First check if it's one of our custom exceptions, if not pass it back.
            IdentityProviderException idex = error as IdentityProviderException;
            if (idex == null)
            {
                return;
            }

            MessageFault messageFault = null;
            CardReferenceException cardReferenceException = idex as CardReferenceException;
            if (cardReferenceException != null)
            {
                InformationCardReference infocard = new InformationCardReference
                                                        {
                                                            CardId = cardReferenceException.CardId,
                                                            CardVersion = cardReferenceException.CardVersion
                                                        };

                messageFault = MessageFault.CreateFault(cardReferenceException.FaultCode, cardReferenceException.FaultReason, infocard);
            }

            FailedRequiredClaimsException failedRequiredClaimsException = idex as FailedRequiredClaimsException;
            if (failedRequiredClaimsException != null && messageFault == null)
            {
                FailedRequiredClaimsFaultBodyWriter writer = new FailedRequiredClaimsFaultBodyWriter(
                    Properties.Resources.FaultFailedRequiredClaims, failedRequiredClaimsException.ClaimTypes);

                fault = Message.CreateMessage(version, Constants.Soap.FaultCodes.Action, writer);
                return;
            }
            
            if (messageFault == null)
            {
                messageFault = MessageFault.CreateFault(idex.FaultCode, idex.FaultReason);
            }

            fault = Message.CreateMessage(version, messageFault, Constants.Soap.FaultCodes.Action);
        }

        /// <summary>
        /// Enables error-related processing and returns a value that indicates whether subsequent HandleError implementations are called.
        /// </summary>
        /// <param name="error">The exception thrown during processing.</param>
        /// <returns>
        /// true if subsequent <see cref="T:System.ServiceModel.Dispatcher.IErrorHandler"/> implementations must not be called; otherwise, false. The default is false.
        /// </returns>
        public bool HandleError(Exception error)
        {
            return error is IdentityProviderException;
        }
    }
}
